using System;
using System.Collections.Generic;
using System.Linq;

namespace MT5Trade.Models
{
    /// <summary>
    /// 夏普比率风险调整器
    /// 基于夏普比率动态调整交易策略的风险参数
    /// </summary>
    public class SharpeRatioRiskAdjuster
    {
        #region 常量定义

        // 夏普比率阈值
        public const double EXCELLENT_SHARPE = 2.0;      // 优秀（>2）
        public const double GOOD_SHARPE = 1.5;           // 良好（1.5-2）
        public const double ACCEPTABLE_SHARPE = 1.0;     // 可接受（1-1.5）
        public const double POOR_SHARPE = 0.5;           // 较差（0.5-1）
        public const double UNACCEPTABLE_SHARPE = 0.0;   // 不可接受（<0.5）

        // 调整系数
        public const double MAX_POSITION_MULTIPLIER = 1.5;  // 最大仓位放大倍数
        public const double MIN_POSITION_MULTIPLIER = 0.3;  // 最小仓位缩小倍数
        public const double RISK_FREE_RATE = 0.02;         // 年化无风险利率（2%）

        // 时间窗口（交易日）
        public const int SHORT_TERM_WINDOW = 20;    // 短期窗口（约1个月）
        public const int MEDIUM_TERM_WINDOW = 60;   // 中期窗口（约3个月）
        public const int LONG_TERM_WINDOW = 252;    // 长期窗口（约1年）

        #endregion

        #region 私有字段

        private readonly List<double> _returns;
        private readonly Dictionary<string, List<double>> _strategyReturns;
        private double _currentSharpeRatio;
        private DateTime _lastUpdateTime;
        private readonly IRandomProvider _randomProvider;

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化夏普比率风险调整器
        /// </summary>
        public SharpeRatioRiskAdjuster(IRandomProvider randomProvider = null)
        {
            _returns = new List<double>();
            _strategyReturns = new Dictionary<string, List<double>>();
            _currentSharpeRatio = 0;
            _lastUpdateTime = DateTime.Now;
            _randomProvider = randomProvider ?? new DeterministicRandomProvider();
        }

        #endregion

        #region 核心计算方法

        /// <summary>
        /// 计算夏普比率
        /// </summary>
        /// <param name="returns">收益率序列</param>
        /// <param name="riskFreeRate">无风险利率（年化）</param>
        /// <param name="periodsPerYear">年化因子（日数据=252，月数据=12）</param>
        /// <returns>夏普比率</returns>
        public double CalculateSharpeRatio(double[] returns, double riskFreeRate = RISK_FREE_RATE, int periodsPerYear = 252)
        {
            if (returns == null || returns.Length < 2)
                return 0;

            // 计算平均收益率
            double meanReturn = returns.Average();
            
            // 计算收益率标准差
            double variance = returns.Select(r => Math.Pow(r - meanReturn, 2)).Sum() / (returns.Length - 1);
            double stdDev = Math.Sqrt(variance);
            
            if (stdDev < 1e-10)
                return 0; // 避免除零

            // 计算日化的无风险利率
            double dailyRiskFreeRate = riskFreeRate / periodsPerYear;
            
            // 计算夏普比率
            double excessReturn = meanReturn - dailyRiskFreeRate;
            double sharpeRatio = (excessReturn * Math.Sqrt(periodsPerYear)) / stdDev;
            
            return sharpeRatio;
        }

        /// <summary>
        /// 计算滚动夏普比率
        /// </summary>
        /// <param name="returns">完整收益率序列</param>
        /// <param name="windowSize">滚动窗口大小</param>
        /// <returns>滚动夏普比率序列</returns>
        public double[] CalculateRollingSharpeRatio(double[] returns, int windowSize = SHORT_TERM_WINDOW)
        {
            if (returns.Length < windowSize)
                return new double[0];

            var rollingSharpe = new List<double>();
            
            for (int i = windowSize - 1; i < returns.Length; i++)
            {
                var window = returns.Skip(i - windowSize + 1).Take(windowSize).ToArray();
                double sharpe = CalculateSharpeRatio(window);
                rollingSharpe.Add(sharpe);
            }
            
            return rollingSharpe.ToArray();
        }

        /// <summary>
        /// 基于夏普比率调整风险参数
        /// </summary>
        /// <param name="currentSharpe">当前夏普比率</param>
        /// <param name="basePosition">基础仓位大小</param>
        /// <param name="baseStopLoss">基础止损比例</param>
        /// <returns>调整后的风险参数</returns>
        public RiskAdjustmentResult AdjustRiskParameters(double currentSharpe, double basePosition, double baseStopLoss)
        {
            var result = new RiskAdjustmentResult
            {
                SharpeRatio = currentSharpe,
                BasePosition = basePosition,
                BaseStopLoss = baseStopLoss,
                Timestamp = DateTime.Now
            };

            // 根据夏普比率计算调整系数
            double positionMultiplier = CalculatePositionMultiplier(currentSharpe);
            double stopLossAdjustment = CalculateStopLossAdjustment(currentSharpe);
            
            // 应用调整
            result.AdjustedPosition = basePosition * positionMultiplier;
            result.AdjustedStopLoss = baseStopLoss * stopLossAdjustment;
            result.PositionMultiplier = positionMultiplier;
            result.StopLossMultiplier = stopLossAdjustment;
            
            // 设置风险等级
            result.RiskLevel = DetermineRiskLevel(currentSharpe);
            
            // 生成建议
            result.Recommendation = GenerateRecommendation(currentSharpe, result.RiskLevel);
            
            return result;
        }

        /// <summary>
        /// 计算仓位调整倍数
        /// </summary>
        private double CalculatePositionMultiplier(double sharpeRatio)
        {
            if (sharpeRatio >= EXCELLENT_SHARPE)
            {
                // 优秀表现，增加仓位（最多1.5倍）
                return Math.Min(1.0 + (sharpeRatio - EXCELLENT_SHARPE) * 0.25, MAX_POSITION_MULTIPLIER);
            }
            else if (sharpeRatio >= GOOD_SHARPE)
            {
                // 良好表现，适度增加（1.1-1.3倍）
                return 1.1 + (sharpeRatio - GOOD_SHARPE) / (EXCELLENT_SHARPE - GOOD_SHARPE) * 0.2;
            }
            else if (sharpeRatio >= ACCEPTABLE_SHARPE)
            {
                // 可接受表现，维持原仓位（0.9-1.1倍）
                return 0.9 + (sharpeRatio - ACCEPTABLE_SHARPE) / (GOOD_SHARPE - ACCEPTABLE_SHARPE) * 0.2;
            }
            else if (sharpeRatio >= POOR_SHARPE)
            {
                // 较差表现，减少仓位（0.5-0.9倍）
                return 0.5 + (sharpeRatio - POOR_SHARPE) / (ACCEPTABLE_SHARPE - POOR_SHARPE) * 0.4;
            }
            else if (sharpeRatio >= UNACCEPTABLE_SHARPE)
            {
                // 不可接受，大幅减少（0.3-0.5倍）
                return MIN_POSITION_MULTIPLIER + (sharpeRatio - UNACCEPTABLE_SHARPE) / POOR_SHARPE * 0.2;
            }
            else
            {
                // 负夏普比率，最小仓位
                return MIN_POSITION_MULTIPLIER;
            }
        }

        /// <summary>
        /// 计算止损调整系数
        /// </summary>
        private double CalculateStopLossAdjustment(double sharpeRatio)
        {
            if (sharpeRatio >= EXCELLENT_SHARPE)
            {
                // 优秀表现，可以放宽止损（1.2-1.5倍）
                return 1.2 + Math.Min((sharpeRatio - EXCELLENT_SHARPE) * 0.15, 0.3);
            }
            else if (sharpeRatio >= ACCEPTABLE_SHARPE)
            {
                // 可接受表现，标准止损（1.0倍）
                return 1.0;
            }
            else if (sharpeRatio >= UNACCEPTABLE_SHARPE)
            {
                // 较差表现，收紧止损（0.7-1.0倍）
                return 0.7 + (sharpeRatio - UNACCEPTABLE_SHARPE) / ACCEPTABLE_SHARPE * 0.3;
            }
            else
            {
                // 负夏普比率，最严格止损（0.5-0.7倍）
                return Math.Max(0.5, 0.7 + sharpeRatio * 0.2);
            }
        }

        /// <summary>
        /// 确定风险等级
        /// </summary>
        private SharpeRiskLevel DetermineRiskLevel(double sharpeRatio)
        {
            if (sharpeRatio >= EXCELLENT_SHARPE)
                return SharpeRiskLevel.VeryLow;
            else if (sharpeRatio >= GOOD_SHARPE)
                return SharpeRiskLevel.Low;
            else if (sharpeRatio >= ACCEPTABLE_SHARPE)
                return SharpeRiskLevel.Medium;
            else if (sharpeRatio >= POOR_SHARPE)
                return SharpeRiskLevel.High;
            else
                return SharpeRiskLevel.VeryHigh;
        }

        /// <summary>
        /// 生成调整建议
        /// </summary>
        private string GenerateRecommendation(double sharpeRatio, SharpeRiskLevel riskLevel)
        {
            if (sharpeRatio >= EXCELLENT_SHARPE)
                return $"策略表现优秀（Sharpe={sharpeRatio:F2}），建议增加仓位至最大允许水平";
            else if (sharpeRatio >= GOOD_SHARPE)
                return $"策略表现良好（Sharpe={sharpeRatio:F2}），可适度增加仓位";
            else if (sharpeRatio >= ACCEPTABLE_SHARPE)
                return $"策略表现可接受（Sharpe={sharpeRatio:F2}），维持当前风险水平";
            else if (sharpeRatio >= POOR_SHARPE)
                return $"策略表现较差（Sharpe={sharpeRatio:F2}），建议减少仓位并收紧止损";
            else if (sharpeRatio >= UNACCEPTABLE_SHARPE)
                return $"策略表现不佳（Sharpe={sharpeRatio:F2}），建议大幅降低风险暴露";
            else
                return $"策略表现极差（Sharpe={sharpeRatio:F2}），建议暂停交易或切换策略";
        }

        #endregion

        #region 高级功能

        /// <summary>
        /// 多策略夏普比率比较与选择
        /// </summary>
        /// <param name="strategies">策略名称与收益率映射</param>
        /// <returns>最优策略选择结果</returns>
        public StrategySelectionResult SelectOptimalStrategy(Dictionary<string, double[]> strategies)
        {
            var result = new StrategySelectionResult
            {
                Timestamp = DateTime.Now,
                StrategyScores = new Dictionary<string, StrategyScore>()
            };

            double bestSharpe = double.NegativeInfinity;
            string bestStrategy = null;

            foreach (var strategy in strategies)
            {
                var score = new StrategyScore
                {
                    StrategyName = strategy.Key,
                    Returns = strategy.Value,
                    SharpeRatio = CalculateSharpeRatio(strategy.Value),
                    AverageReturn = strategy.Value.Average(),
                    Volatility = Math.Sqrt(strategy.Value.Select(r => Math.Pow(r - strategy.Value.Average(), 2)).Average()),
                    MaxDrawdown = CalculateMaxDrawdown(strategy.Value)
                };

                // 计算综合得分（夏普比率为主，考虑最大回撤）
                score.CompositeScore = score.SharpeRatio * 0.7 - score.MaxDrawdown * 0.3;
                
                result.StrategyScores[strategy.Key] = score;

                if (score.SharpeRatio > bestSharpe)
                {
                    bestSharpe = score.SharpeRatio;
                    bestStrategy = strategy.Key;
                }
            }

            result.OptimalStrategy = bestStrategy;
            result.OptimalSharpeRatio = bestSharpe;
            
            // 计算策略配置权重（基于夏普比率）
            result.AllocationWeights = CalculateOptimalWeights(result.StrategyScores);
            
            return result;
        }

        /// <summary>
        /// 计算最大回撤
        /// </summary>
        private double CalculateMaxDrawdown(double[] returns)
        {
            double peak = 0;
            double maxDrawdown = 0;
            double cumReturn = 1.0;

            foreach (var ret in returns)
            {
                cumReturn *= (1 + ret);
                if (cumReturn > peak)
                    peak = cumReturn;
                
                double drawdown = (peak - cumReturn) / peak;
                if (drawdown > maxDrawdown)
                    maxDrawdown = drawdown;
            }

            return maxDrawdown;
        }

        /// <summary>
        /// 计算策略最优配置权重
        /// </summary>
        private Dictionary<string, double> CalculateOptimalWeights(Dictionary<string, StrategyScore> scores)
        {
            var weights = new Dictionary<string, double>();
            double totalPositiveSharpe = 0;

            // 只考虑正夏普比率的策略
            foreach (var score in scores.Values.Where(s => s.SharpeRatio > 0))
            {
                totalPositiveSharpe += score.SharpeRatio;
            }

            if (totalPositiveSharpe > 0)
            {
                foreach (var score in scores.Values)
                {
                    if (score.SharpeRatio > 0)
                    {
                        // 基于夏普比率的比例分配
                        weights[score.StrategyName] = score.SharpeRatio / totalPositiveSharpe;
                    }
                    else
                    {
                        weights[score.StrategyName] = 0;
                    }
                }
            }
            else
            {
                // 如果没有正夏普比率，平均分配
                double equalWeight = 1.0 / scores.Count;
                foreach (var strategy in scores.Keys)
                {
                    weights[strategy] = equalWeight;
                }
            }

            return weights;
        }

        /// <summary>
        /// 动态夏普比率目标调整
        /// </summary>
        /// <param name="marketVolatility">市场波动率</param>
        /// <param name="baseTarget">基础目标夏普比率</param>
        /// <returns>调整后的目标夏普比率</returns>
        public double AdjustSharpeTarget(double marketVolatility, double baseTarget = 1.5)
        {
            // 高波动市场降低夏普比率预期
            // 低波动市场提高夏普比率预期
            double volatilityAdjustment = 1.0;
            
            if (marketVolatility < 0.1) // 低波动
            {
                volatilityAdjustment = 1.2;
            }
            else if (marketVolatility < 0.2) // 正常波动
            {
                volatilityAdjustment = 1.0;
            }
            else if (marketVolatility < 0.3) // 高波动
            {
                volatilityAdjustment = 0.8;
            }
            else // 极高波动
            {
                volatilityAdjustment = 0.6;
            }
            
            return baseTarget * volatilityAdjustment;
        }

        #endregion

        #region 数据更新与管理

        /// <summary>
        /// 更新收益率数据
        /// </summary>
        public void UpdateReturns(double newReturn)
        {
            _returns.Add(newReturn);
            
            // 保持数据窗口大小
            if (_returns.Count > LONG_TERM_WINDOW)
            {
                _returns.RemoveAt(0);
            }
            
            // 重新计算当前夏普比率
            if (_returns.Count >= SHORT_TERM_WINDOW)
            {
                _currentSharpeRatio = CalculateSharpeRatio(_returns.ToArray());
            }
            
            _lastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 获取当前夏普比率
        /// </summary>
        public double GetCurrentSharpeRatio()
        {
            return _currentSharpeRatio;
        }

        /// <summary>
        /// 获取历史夏普比率统计
        /// </summary>
        public SharpeRatioStatistics GetStatistics()
        {
            if (_returns.Count < SHORT_TERM_WINDOW)
            {
                return new SharpeRatioStatistics
                {
                    InsufficientData = true
                };
            }

            var shortTermReturns = _returns.TakeLast(SHORT_TERM_WINDOW).ToArray();
            var mediumTermReturns = _returns.Count >= MEDIUM_TERM_WINDOW ? 
                _returns.TakeLast(MEDIUM_TERM_WINDOW).ToArray() : _returns.ToArray();
            var longTermReturns = _returns.Count >= LONG_TERM_WINDOW ? 
                _returns.TakeLast(LONG_TERM_WINDOW).ToArray() : _returns.ToArray();

            return new SharpeRatioStatistics
            {
                ShortTermSharpe = CalculateSharpeRatio(shortTermReturns),
                MediumTermSharpe = CalculateSharpeRatio(mediumTermReturns),
                LongTermSharpe = CalculateSharpeRatio(longTermReturns),
                CurrentSharpe = _currentSharpeRatio,
                DataPoints = _returns.Count,
                LastUpdate = _lastUpdateTime,
                InsufficientData = false
            };
        }

        #endregion
    }

    #region 辅助类定义

    /// <summary>
    /// 风险调整结果
    /// </summary>
    public class RiskAdjustmentResult
    {
        public double SharpeRatio { get; set; }
        public double BasePosition { get; set; }
        public double AdjustedPosition { get; set; }
        public double BaseStopLoss { get; set; }
        public double AdjustedStopLoss { get; set; }
        public double PositionMultiplier { get; set; }
        public double StopLossMultiplier { get; set; }
        public SharpeRiskLevel RiskLevel { get; set; }
        public string Recommendation { get; set; }
        public DateTime Timestamp { get; set; }
    }

    /// <summary>
    /// 策略选择结果
    /// </summary>
    public class StrategySelectionResult
    {
        public Dictionary<string, StrategyScore> StrategyScores { get; set; }
        public string OptimalStrategy { get; set; }
        public double OptimalSharpeRatio { get; set; }
        public Dictionary<string, double> AllocationWeights { get; set; }
        public DateTime Timestamp { get; set; }
    }

    /// <summary>
    /// 策略评分
    /// </summary>
    public class StrategyScore
    {
        public string StrategyName { get; set; }
        public double[] Returns { get; set; }
        public double SharpeRatio { get; set; }
        public double AverageReturn { get; set; }
        public double Volatility { get; set; }
        public double MaxDrawdown { get; set; }
        public double CompositeScore { get; set; }
    }

    /// <summary>
    /// 夏普比率统计
    /// </summary>
    public class SharpeRatioStatistics
    {
        public double ShortTermSharpe { get; set; }
        public double MediumTermSharpe { get; set; }
        public double LongTermSharpe { get; set; }
        public double CurrentSharpe { get; set; }
        public int DataPoints { get; set; }
        public DateTime LastUpdate { get; set; }
        public bool InsufficientData { get; set; }
    }

    /// <summary>
    /// 夏普比率风险等级
    /// </summary>
    public enum SharpeRiskLevel
    {
        VeryLow,    // 非常低
        Low,        // 低
        Medium,     // 中等
        High,       // 高
        VeryHigh    // 非常高
    }

    #endregion
}